package uk.ac.lkl.lpp.ui;



import java.awt.Component;
import java.awt.Dimension;

import javax.swing.JTable;

import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableModel;


// todo: integrate this functionality into sub-class
public class ColumnSizer implements TableModelListener {

    /**
     * The amount of space that will be added to the maximum preferred
     * width of a column so as to avoid 'ellipsis'.
     * 
     */
    public static final int WIDTH_SUPPLEMENT = 5;

    /**
     * The tableView.
     * 
     */
    private JTable tableView;

    /**
     * The index that this instance processes.
     * 
     */
    private int columnIndex;

    /**
     * The model of the table.
     * 
     * Note that this is currently stored at construction time.
     * Switching to a different model within the table view will
     * currently now work with this class.
     * 
     */
    private TableModel tableModel;

    /**
     * The TableColumn for this instance.
     * 
     */
    private TableColumn column;


    public ColumnSizer(JTable tableView,
            int columnIndex) {
        this.tableView = tableView;
        this.tableModel = tableView.getModel();
        this.column = tableView.getColumnModel().getColumn(columnIndex);
        this.columnIndex = columnIndex;
        sizeColumn();
    }


    public void tableChanged(TableModelEvent e) {
        // if is modifying whole rows then this doesn't work
        // since col is -1
        // if (e.getColumn() != column.getModelIndex())
        // return;
        int preferredWidth = column.getPreferredWidth();

        // hack: do nothing if zero sized. Means that contents won't update properly.
        if (preferredWidth == 0)
            return;
        
        sizeColumn();
    }


    private void sizeColumn() {
        int maxWidth = getPreferredHeaderWidth();

        // int maxWidth = 0;
        for (int rowIndex = 0; rowIndex < tableModel.getRowCount(); rowIndex++) {
            int preferredCellWidth = getPreferredCellWidth(rowIndex);
            maxWidth = Math.max(preferredCellWidth, maxWidth);
        }

        column.setPreferredWidth(maxWidth + WIDTH_SUPPLEMENT);
        tableView.doLayout();
    }


    private int getPreferredHeaderWidth() {
        TableCellRenderer headerRenderer = column.getHeaderRenderer();
        if (headerRenderer == null)
            headerRenderer = tableView.getTableHeader().getDefaultRenderer();
        Object headerValue = tableModel.getColumnName(columnIndex);
        Component headerComponent = headerRenderer.getTableCellRendererComponent(tableView,
                                                                                 headerValue,
                                                                                 false,
                                                                                 false,
                                                                                 0,
                                                                                 columnIndex);
        Dimension preferredHeaderSize = headerComponent.getPreferredSize();
        return preferredHeaderSize.width;
    }


    private int getPreferredCellWidth(int rowIndex) {
        TableCellRenderer renderer = tableView.getCellRenderer(rowIndex,
                                                               columnIndex);
        Object value = tableModel.getValueAt(rowIndex, columnIndex);
        Component component = renderer.getTableCellRendererComponent(tableView,
                                                                     value,
                                                                     false,
                                                                     false,
                                                                     rowIndex,
                                                                     columnIndex);
        Dimension preferredCellSize = component.getPreferredSize();
        return preferredCellSize.width;
    }

};